package venndiagram;

import java.awt.Point;
import java.util.ArrayList;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Adam
 */
public class GraphDataThreeSets implements GraphData
{
    private String aName;
    private String bName;
    private String cName;

    private int a;
    private int b;
    private int c;
    private int ab;
    private int ac;
    private int bc;
    private int abc;

    protected CircleData maxCircle;
    protected CircleData midCircle;
    protected CircleData minCircle;
    private final double MAX_RADIUS;
    private final int MAX_ELEMENTS;
    private final int MID_ELEMENTS;
    private ArrayList<Integer> counts = new ArrayList<Integer>(7);

    public GraphDataThreeSets(String aName, String bName, String cName, int a, int b, int c, int ab, int ac, int bc, int abc)
    {
        //Set Names
        this.aName = aName;
        this.bName = bName;
        this.cName = cName;

        //Number of elements in each subset
        this.a = a;
        this.b = b;
        this.c = c;
        this.ab = ab;
        this.ac = ac;
        this.bc = bc;
        this.abc = abc;

        //Get total number of elements in each set
        int aTotal = a + ab + ac + abc;
        int bTotal = b + ab + bc + abc;
        int cTotal = c + ac + bc + abc;

        //Initialize max, mid and min circles; set max radius
        if(aTotal >= bTotal && aTotal >= cTotal)
        {
            //Record number of elements in largest circle
            MAX_ELEMENTS = aTotal;

            //Create maxCircle based on set a
            MAX_RADIUS = Math.sqrt(aTotal / Math.PI);
            this.maxCircle = new CircleData(MAX_RADIUS, new Point(0,0), this.aName);
            //Create mid and min circles based on sets b and c, respectively
            if(bTotal >= cTotal)
            {
                //Record number of elements in second largest circle
                MID_ELEMENTS = bTotal;
        
                //set the counts of all of the sets. The max, mid and min is determined by order
                setCounts(this.a, this.b, this.c, this.ab, this.bc, this.ac, this.abc);

                this.midCircle = new CircleData(Math.sqrt(bTotal / Math.PI), new Point(0,0), this.bName);
                this.minCircle = new CircleData(Math.sqrt(cTotal / Math.PI), new Point(0,0), this.cName);
            }
            //Create mid and min circles based on sets c and b, respectively
            else
            {
                //Record number of elements in second largest circle
                MID_ELEMENTS = cTotal;
                
                //set the counts of all of the sets. The max, mid and min is determined by order
                setCounts(this.a, this.c, this.b, this.ac, this.bc, this.ab, this.abc);

               this.midCircle = new CircleData(Math.sqrt(cTotal / Math.PI), new Point(0,0), this.cName);
               this.minCircle = new CircleData(Math.sqrt(bTotal / Math.PI), new Point(0,0), this.bName); 
            }
        }
        else if(bTotal >= cTotal)
        {
            //Record number of elements in largest circle
            MAX_ELEMENTS = bTotal;

            //Create maxCircle based on set b
            MAX_RADIUS = Math.sqrt(bTotal / Math.PI);
            this.maxCircle = new CircleData(MAX_RADIUS, new Point(0,0), this.bName);
            //Create mid and min circles based on sets a and c, respectively
            if(aTotal >= cTotal)
            {
                //Record number of elements in second largest circle
                MID_ELEMENTS = aTotal;
                
                //set the counts of all of the sets. The max, mid and min is determined by order
                setCounts(this.b, this.a, this.c, this.ab, this.ac, this.bc, this.abc);

                this.midCircle = new CircleData(Math.sqrt(aTotal / Math.PI), new Point(0,0), this.aName);
                this.minCircle = new CircleData(Math.sqrt(cTotal / Math.PI), new Point(0,0), this.cName);
            }
            //Create mid and min circles based on sets c and a, respectively
            else
            {
                //Record number of elements in second largest circle
                MID_ELEMENTS = cTotal;
                
                setCounts(this.b, this.c, this.a, this.bc, this.ac, this.ab, this.abc);

               this.midCircle = new CircleData(Math.sqrt(cTotal / Math.PI), new Point(0,0), this.cName);
               this.minCircle = new CircleData(Math.sqrt(aTotal / Math.PI), new Point(0,0), this.aName);
            }
        }
        else
        {
            //Record number of elements in largest circle
            MAX_ELEMENTS = cTotal;

            //Create maxCircle based on set c
            MAX_RADIUS = Math.sqrt(cTotal / Math.PI);
            this.maxCircle = new CircleData(MAX_RADIUS, new Point(0,0), this.cName);
            //Create mid and min circles based on sets a and b, respectively
            if(aTotal >= bTotal)
            {
                //Record number of elements in second largest circle
                MID_ELEMENTS = aTotal;
                
                setCounts(this.c, this.a, this.b, this.ac, this.ab, this.bc, this.abc);

                this.midCircle = new CircleData(Math.sqrt(aTotal / Math.PI), new Point(0,0), this.aName);
                this.minCircle = new CircleData(Math.sqrt(bTotal / Math.PI), new Point(0,0), this.bName);
            }
            //Create mid and min circles based on sets b and a, respectively
            else
            {
                //Record number of elements in second largest circle
                MID_ELEMENTS = bTotal;
                
                setCounts(this.c, this.b, this.a, this.bc, this.ab, this.ac, this.abc);

               this.midCircle = new CircleData(Math.sqrt(bTotal / Math.PI), new Point(0,0), this.bName);
               this.minCircle = new CircleData(Math.sqrt(aTotal / Math.PI), new Point(0,0), this.aName);
            }
        }
    }


    @Override
    //Find and set centers for all three circles
    public void findCenters()
    {
        double intMidMaxToMax;    //Ratio of intersection between max and mid circles to max circle

        //Use intersection of sets a and b for ratio
        if((maxCircle.getName().equals(this.aName)) && (midCircle.getName().equals(this.bName) ||
          (maxCircle.getName().equals(this.bName)) && (midCircle.getName().equals(this.aName))))
            intMidMaxToMax = (double) (ab + abc) / (MAX_ELEMENTS);

        //Use intersection of sets a and c for ratio
        else if((maxCircle.getName().equals(this.aName)) && (midCircle.getName().equals(this.cName) ||
          (maxCircle.getName().equals(this.cName)) && (midCircle.getName().equals(this.aName))))
            intMidMaxToMax = (double) (ac + abc) / (MAX_ELEMENTS);

        //Use intersection of sets b and c for ratio
        else
            intMidMaxToMax = (double) (bc + abc) / (MAX_ELEMENTS);

        //Initialize distance so the circles don't intersect
        int midMaxDistance = (int) (maxCircle.getRadius() + midCircle.getRadius() + 1);

        double midMaxIntersection;    //Area of intersection of max and mid circles

        //Decrease distance until area of intersection at current distance is greater than previously calculated area of intersection
        do
        {
            midMaxDistance--;
            midMaxIntersection = findIntersection(maxCircle.getRadius(), midCircle.getRadius(), midMaxDistance);
        }
        while(midMaxIntersection / MAX_ELEMENTS < intMidMaxToMax);

        //Increment distance once if distance + 1 is more accurate than current distance
        if(Math.abs(findIntersection(maxCircle.getRadius(), midCircle.getRadius(), midMaxDistance + 1) - intMidMaxToMax) <
           Math.abs(findIntersection(maxCircle.getRadius(), midCircle.getRadius(), midMaxDistance) - intMidMaxToMax))
            midMaxDistance += 1;

        //Set midCircle center
        midCircle.setCenter(new Point((int)midMaxDistance, 0));
        
        //Calculate center for minCricle
        //Get distance between centers of min and max circles
        
        double intMinMaxToMax;  //Ratio of intersection between min and max circles to max circle
        
        //Use intersection of sets a and b for ratio
        if((maxCircle.getName().equals(this.aName)) && (minCircle.getName().equals(this.bName) ||
          (maxCircle.getName().equals(this.bName)) && (minCircle.getName().equals(this.aName))))
            intMinMaxToMax = (double)(ab + abc)/ (MAX_ELEMENTS);

        //Use intersection of sets a and c for ratio
        else if((maxCircle.getName().equals(this.aName)) && (minCircle.getName().equals(this.cName) ||
          (maxCircle.getName().equals(this.cName)) && (minCircle.getName().equals(this.aName))))
            intMinMaxToMax = (double)(ac + abc)/ (MAX_ELEMENTS);

        //Use intersection of sets b and c for ration
        else
            intMinMaxToMax = (double)(bc + abc)/ (MAX_ELEMENTS);

        //Initialize distance so the circles don't intersect
        int minMaxDistance = (int) (maxCircle.getRadius() + minCircle.getRadius() + 1);

        double minMaxIntersection;    //Area of intersection of max and min circles

        //Decrease distance until area of intersection at current distance is greater than previously calculated area of intersection
        do
        {
            minMaxDistance--;
            minMaxIntersection = findIntersection(maxCircle.getRadius(), minCircle.getRadius(), minMaxDistance);
        }
        while(minMaxIntersection / MAX_ELEMENTS < intMinMaxToMax);

        //Increment distance once if distance + 1 is more accurate than current distance
        if(Math.abs(findIntersection(maxCircle.getRadius(), minCircle.getRadius(), minMaxDistance + 1) - intMinMaxToMax) <
           Math.abs(findIntersection(maxCircle.getRadius(), minCircle.getRadius(), minMaxDistance) - intMinMaxToMax))
            minMaxDistance += 1;

        //Record x of minCricle's center when at proper distance from maxCircle before rotation
        final int X_BEFORE_ROTATE = 0 - minMaxDistance;
        
        double intMinMidToMid;    //Ratio of intersection between min and mid circles to mid circle

        //Use intersection of sets a and b for ratio
        if((minCircle.getName().equals(this.aName)) && (midCircle.getName().equals(this.bName) ||
          (minCircle.getName().equals(this.bName)) && (midCircle.getName().equals(this.aName))))
            intMinMidToMid = (double)(ab + abc) / (MID_ELEMENTS);

        //Use intersection of sets a and c for ratio
        else if((minCircle.getName().equals(this.aName)) && (midCircle.getName().equals(this.cName) ||
          (minCircle.getName().equals(this.cName)) && (midCircle.getName().equals(this.aName))))
            intMinMidToMid = (double)(ac + abc)/ (MID_ELEMENTS);

        //Use intersection of sets b and c for ratio
        else
            intMinMidToMid = (double)(bc + abc)/ (MID_ELEMENTS);

        double minMidIntersection;    //Area of intersection of max and mid circles
        
        int xAfterRotation; //Value of minCircle's x coordinate after rotation
        int yAfterRotation; //Value of minCircle's y coordinate after rotation
        double angle = 0.0; //Angle of rotation to be used
        double minMidDistance;  //Distance between center of min and mid circles
        
        //Roate minCircle's center until area of intersection at current distance is greater than previously calculated area of intersection
        do
        {
            //Perform rotation
            xAfterRotation = (int) (X_BEFORE_ROTATE * Math.cos(angle));
            yAfterRotation = (int) (X_BEFORE_ROTATE * Math.sin(angle));
            
            //Find distance between centers of minCircle and midCircle
            minMidDistance = Math.sqrt(((xAfterRotation - midCircle.getCenter().getX()) *
                    (xAfterRotation - midCircle.getCenter().getX())) +
                    ((yAfterRotation - midCircle.getCenter().getY()) *
                    (yAfterRotation - midCircle.getCenter().getY())));
            
            //Find area of intersection of min and mid circles
            minMidIntersection = findIntersection(midCircle.getRadius(), minCircle.getRadius(), minMidDistance);

            //Increment angle
            angle = angle + 0.01;
        }
        while(minMidIntersection / (MID_ELEMENTS) < intMinMidToMid && angle < 360);
        
        //TODO Check adjacent points for better accuracy
        
        //Set minCircle center
        minCircle.setCenter(new Point(xAfterRotation,yAfterRotation));
    }
    
    public void resize()
    {
        //Get circle with lowest valued tangent perpendicular to x axis for repositioning
        CircleData minXEdgeCircle = new CircleData();   //Circle with smallest value x edge
        if((maxCircle.getCenter().getX() - maxCircle.getRadius()) < (midCircle.getCenter().getX() - midCircle.getRadius()))
            minXEdgeCircle = maxCircle;
        else
            minXEdgeCircle = midCircle;
        if((minXEdgeCircle.getCenter().getX() - minXEdgeCircle.getRadius()) > (minCircle.getCenter().getX() - minCircle.getRadius()))
            minXEdgeCircle = minCircle;

        //Get circle with lowest valued tangent perpendicular to y axis for repositioning
        CircleData minYEdgeCircle = new CircleData();   //Circle with smallest value y edge
        if((maxCircle.getCenter().getY() - maxCircle.getRadius()) < (midCircle.getCenter().getY() - midCircle.getRadius()))
            minYEdgeCircle = maxCircle;
        else
            minYEdgeCircle = midCircle;
        if((minYEdgeCircle.getCenter().getY() - minYEdgeCircle.getRadius()) > (minCircle.getCenter().getY() - minCircle.getRadius()))
            minYEdgeCircle = minCircle;

        //Find x and y offset to shift circles' centers by so that all points within all circles contain only positive coordinates
        int xOffset = (int) (minXEdgeCircle.getRadius() - minXEdgeCircle.getCenter().getX());    //X offset to shift centers by
        int yOffset = (int) (minYEdgeCircle.getRadius() - minYEdgeCircle.getCenter().getY());    //Y offset to shift centers by

        //Shift circles' centers by calculated coordinates
        maxCircle.setCenter(new Point((maxCircle.getCenter().x + xOffset),(maxCircle.getCenter().y + yOffset)));
        midCircle.setCenter(new Point((midCircle.getCenter().x + xOffset),(midCircle.getCenter().y + yOffset)));
        minCircle.setCenter(new Point((minCircle.getCenter().x + xOffset),(minCircle.getCenter().y + yOffset)));

        //Values for determining how to fit diagram to screen
        int screenWidth = 476;  //Width of screen to fit diagram to
        int screenHeight = 357; //Height of screen to fit diagram to
        int padding = 40;       //Amount of padding to allow between edge of screen and diagram

        int diagramWidth;       //Width of diagram before resize
        int diagramHeight;     //Height of diagram before resize

        //Calculate width of diagram before resize
        if((maxCircle.getCenter().x + maxCircle.getRadius()) > (midCircle.getCenter().x + midCircle.getRadius()))
        {
            if((maxCircle.getCenter().x + maxCircle.getRadius()) > (minCircle.getCenter().x + minCircle.getRadius()))
                diagramWidth = (int) ((int) (maxCircle.getCenter().x + maxCircle.getRadius()) - (minXEdgeCircle.getCenter().x - minXEdgeCircle.getRadius()));
            else
                diagramWidth = (int) ((int) (minCircle.getCenter().x + minCircle.getRadius()) - (minXEdgeCircle.getCenter().x - minXEdgeCircle.getRadius()));
        }
        else
        {
            if((midCircle.getCenter().x + midCircle.getRadius()) > (minCircle.getCenter().x + minCircle.getRadius()))
                diagramWidth = (int) ((int) (midCircle.getCenter().x + midCircle.getRadius()) - (minXEdgeCircle.getCenter().x - minXEdgeCircle.getRadius()));
            else
                diagramWidth = (int) ((int) (minCircle.getCenter().x + minCircle.getRadius()) - (minXEdgeCircle.getCenter().x - minXEdgeCircle.getRadius()));
        }

        //Calculate height of diagram before resize
        if((maxCircle.getCenter().y + maxCircle.getRadius()) > (midCircle.getCenter().y + midCircle.getRadius()))
        {
            if((maxCircle.getCenter().y + maxCircle.getRadius()) > (minCircle.getCenter().y + minCircle.getRadius()))
                diagramHeight = (int) ((int) (maxCircle.getCenter().y + maxCircle.getRadius()) - (minXEdgeCircle.getCenter().y - minXEdgeCircle.getRadius()));
            else
                diagramHeight = (int) ((int) (minCircle.getCenter().y + minCircle.getRadius()) - (minXEdgeCircle.getCenter().y - minXEdgeCircle.getRadius()));
        }
        else
        {
            if((midCircle.getCenter().y + midCircle.getRadius()) > (minCircle.getCenter().y + minCircle.getRadius()))
                diagramHeight = (int) ((int) (midCircle.getCenter().y + midCircle.getRadius()) - (minXEdgeCircle.getCenter().y - minXEdgeCircle.getRadius()));
            else
                diagramHeight = (int) ((int) (minCircle.getCenter().y + minCircle.getRadius()) - (minXEdgeCircle.getCenter().y - minXEdgeCircle.getRadius()));
        }

        //Determine whether to fit by width or by height and modify multiplier accordingly
        double multiplier;  //Multiplier to resize diagram by

        //Fit by width
        if(diagramWidth/diagramHeight > screenWidth/screenHeight)
            multiplier = (screenWidth - padding) / diagramWidth;
        //Fit by height
        else
            multiplier = (screenHeight - padding) / diagramHeight;

        //Perform resize operation
        int newX = (int) (maxCircle.getCenter().x * multiplier);    //New x coordinate for center of circle
        int newY = (int) (maxCircle.getCenter().y * multiplier);    //New y coordinate for center of circle
        maxCircle.setCenter(new Point(newX,newY));
        maxCircle.setRadius(maxCircle.getRadius() * multiplier);

        newX = (int) (midCircle.getCenter().x * multiplier);
        newY = (int) (midCircle.getCenter().y * multiplier);
        midCircle.setCenter(new Point(newX,newY));
        midCircle.setRadius(midCircle.getRadius() * multiplier);

        newX = (int) (minCircle.getCenter().x * multiplier);
        newY = (int) (minCircle.getCenter().y * multiplier);
        minCircle.setCenter(new Point(newX,newY));
        minCircle.setRadius(minCircle.getRadius() * multiplier);
        
        //Calculate width of diagram after resize
        if((maxCircle.getCenter().x + maxCircle.getRadius()) > (midCircle.getCenter().x + midCircle.getRadius()))
        {
            if((maxCircle.getCenter().x + maxCircle.getRadius()) > (minCircle.getCenter().x + minCircle.getRadius()))
                diagramWidth = (int) ((int) (maxCircle.getCenter().x + maxCircle.getRadius()) - (minXEdgeCircle.getCenter().x - minXEdgeCircle.getRadius()));
            else
                diagramWidth = (int) ((int) (minCircle.getCenter().x + minCircle.getRadius()) - (minXEdgeCircle.getCenter().x - minXEdgeCircle.getRadius()));
        }
        else
        {
            if((midCircle.getCenter().x + midCircle.getRadius()) > (minCircle.getCenter().x + minCircle.getRadius()))
                diagramWidth = (int) ((int) (midCircle.getCenter().x + midCircle.getRadius()) - (minXEdgeCircle.getCenter().x - minXEdgeCircle.getRadius()));
            else
                diagramWidth = (int) ((int) (minCircle.getCenter().x + minCircle.getRadius()) - (minXEdgeCircle.getCenter().x - minXEdgeCircle.getRadius()));
        }

        //Calculate height of diagram after resize
        if((maxCircle.getCenter().y + maxCircle.getRadius()) > (midCircle.getCenter().y + midCircle.getRadius()))
        {
            if((maxCircle.getCenter().y + maxCircle.getRadius()) > (minCircle.getCenter().y + minCircle.getRadius()))
                diagramHeight = (int) ((int) (maxCircle.getCenter().y + maxCircle.getRadius()) - (minXEdgeCircle.getCenter().y - minXEdgeCircle.getRadius()));
            else
                diagramHeight = (int) ((int) (minCircle.getCenter().y + minCircle.getRadius()) - (minXEdgeCircle.getCenter().y - minXEdgeCircle.getRadius()));
        }
        else
        {
            if((midCircle.getCenter().y + midCircle.getRadius()) > (minCircle.getCenter().y + minCircle.getRadius()))
                diagramHeight = (int) ((int) (midCircle.getCenter().y + midCircle.getRadius()) - (minXEdgeCircle.getCenter().y - minXEdgeCircle.getRadius()));
            else
                diagramHeight = (int) ((int) (minCircle.getCenter().y + minCircle.getRadius()) - (minXEdgeCircle.getCenter().y - minXEdgeCircle.getRadius()));
        }
        
//        System.out.println("Diagram width after resize: " + diagramWidth);
//        System.out.println("Diagram height after resize: " + diagramHeight);
//        System.out.println("");
//        System.out.println("Max circle center after resize: " + maxCircle.getCenter());
//        System.out.println("Max circle radius after resize: " + maxCircle.getRadius());
//        System.out.println("Mid circle center after resize: " + midCircle.getCenter());
//        System.out.println("Mid circle radius after resize: " + midCircle.getRadius());
//        System.out.println("Min circle center after resize: " + minCircle.getCenter());
//        System.out.println("Min circle radius after resize: " + minCircle.getRadius());
//        System.out.println("");
        
        //Find value to shift centers by horizontally to center by width
        int shiftToCenterByWidth = (int)((screenWidth - diagramWidth) / 2);
//        
//        //Find value to shift centers by vertically to center by height
//        int shiftToCenterByHeight = (int)((screenHeight - diagramHeight) / 2);
//        
//        System.out.println("Shift horizontal: " + shiftToCenterByWidth);
//        System.out.println("Shift vertical: " + shiftToCenterByHeight);
        
        //Shift diagram on screen according to width and padding
        maxCircle.setCenter(new Point((int)(maxCircle.getCenter().getX() + (shiftToCenterByWidth)),((int)(maxCircle.getCenter().getY() + (padding / 2)))));
        midCircle.setCenter(new Point((int)(midCircle.getCenter().getX() + (shiftToCenterByWidth)),((int)(midCircle.getCenter().getY() + (padding / 2)))));
        minCircle.setCenter(new Point((int)(minCircle.getCenter().getX() + (shiftToCenterByWidth)),((int)(minCircle.getCenter().getY() + (padding / 2)))));
        
//        //Center all circles' centers to center diagram on screen for resize by width
//        if(diagramWidth/diagramHeight > screenWidth/screenHeight)
//        {
//        maxCircle.setCenter(new Point((int)(maxCircle.getCenter().getX() + shiftToCenterByWidth),((int)(maxCircle.getCenter().getY() + (padding / 2)))));
//        midCircle.setCenter(new Point((int)(midCircle.getCenter().getX() + shiftToCenterByWidth),((int)(midCircle.getCenter().getY() + (padding / 2)))));
//        minCircle.setCenter(new Point((int)(minCircle.getCenter().getX() + shiftToCenterByWidth),((int)(minCircle.getCenter().getY() + (padding / 2)))));
//        }
//        //Center all circles' centers to center diagram on screen for resize by height
//        else
//        {       
//            //Shift all circles' centers to center diagram to screen
//            maxCircle.setCenter(new Point((int)(maxCircle.getCenter().getX() + (padding / 2)),((int)(maxCircle.getCenter().getY() + shiftToCenterByHeight))));
//            midCircle.setCenter(new Point((int)(midCircle.getCenter().getX() + (padding / 2)),((int)(midCircle.getCenter().getY() + shiftToCenterByHeight))));
//            minCircle.setCenter(new Point((int)(minCircle.getCenter().getX() + (padding / 2)),((int)(minCircle.getCenter().getY() + shiftToCenterByHeight))));
//        }
    }

    //Find the area of intersection for two circles
    public double findIntersection(double radius1, double radius2, double distance)
    {
        if(distance >= radius1 + radius2)
            return 0.0;
        else if(radius1 != radius2)
            return (radius1 * radius1 * Math.acos((distance * distance + radius1 * radius1 - radius2 * radius2) / (2 * distance * radius1))) +
               (radius2 * radius2 * Math.acos((distance * distance + radius2 * radius2 - radius1 * radius1) / (2 * distance * radius2))) -
               (0.5 * Math.sqrt((radius1 + radius2 - distance) * (radius1 - radius2 + distance) * (radius2 - radius1 + distance) * (radius1 + radius2 + distance)));
        else
            return (2 * radius2 * radius2 * Math.acos(distance / (2 * radius2)) - 0.5 * distance * Math.sqrt(4 * radius2 * radius2 - distance * distance));
    }
    
    public String getMaxSetName(){
        return maxCircle.getName();
    }
    
    public String getMidSetName(){
        return midCircle.getName();
    }
    
    public String getMinSetName(){
        return minCircle.getName();
    }
    
    public ArrayList<Integer> getSetCounts(){
        return counts;
    }
    
    //sets the counts of all the subsets. This order matters because this 
    //is the order in which the different subsets are drawn
    private void setCounts(Integer max, Integer mid, Integer min, Integer maxMid, Integer midMin, Integer maxMin, Integer maxMidMin){
        counts.add(0, max);
        counts.add(1, mid);
        counts.add(2, min);
        counts.add(3, maxMid);
        counts.add(4, midMin);
        counts.add(5, maxMin);
        counts.add(6, maxMidMin);
    }

}
